package glassline;

import glassline.Glass.GlassCondition;
import glassline.interfaces.Robot;
import transducer.TChannel;
import transducer.TEvent;
import transducer.TReceiver;
import transducer.Transducer;
import agent.Agent;

public class RobotAgent extends Agent implements TReceiver, Robot {
	public enum RobotState {
		Idle,
		Working,
	}
	public RobotState state = RobotState.Idle;
	public int numPiecesInQueue = 0;
	
	NCCutterAgent cutter;

	public RobotAgent(Transducer t) {
		super(t);
		
		// Register channel with the transducer
		myTransducer.register(this, TChannel.Robot);
	}
	
	// Messages
	
	/* (non-Javadoc)
	 * @see glassline.Robot#msgGetGlassFromBin()
	 */
	@Override
	public void msgGetGlassFromBin() {
		numPiecesInQueue++;
		stateChanged();
	}

	/* (non-Javadoc)
	 * @see glassline.Robot#msgDoneMovingGlass(glassline.Glass)
	 */
	@Override
	public void msgDoneMovingGlass(Glass g) { // From GUI after the robot arm finishes moving a piece of glass to the NCCutter.
		numPiecesInQueue--;
		state = RobotState.Idle;
		g.addCondition(GlassCondition.Processing);
		stateChanged();
	}
	
	/* (non-Javadoc)
	 * @see glassline.Robot#pickAndExecuteAnAction()
	 */
	@Override
	public boolean pickAndExecuteAnAction() {
		if (state == RobotState.Idle) { // Can't do anything until the robot arm isn't busy.
		
			// Rule #1
			if (numPiecesInQueue > 0) {
				GetGlassFromBin();
				return true;
			}
		}
		
		return false;
	}
	
	// Transducer event listener.
	/* (non-Javadoc)
	 * @see glassline.Robot#eventFired(transducer.TChannel, transducer.TEvent, java.lang.Object[])
	 */
	@Override
	public void eventFired(TChannel channel, TEvent event, Object[] args) {
		if (channel != TChannel.Robot) return; // Ignore if event isn't on the NCCutter channel
		
		// Check the event fired.
		if (event == TEvent.GLASS_MOVED) {
			// Expected arguments:
			// Glass - reference to the glass that just got to the first conveyor.
			this.msgDoneMovingGlass((Glass)args[0]); // Send message to self as if the GUIRobot sent it.
		}
	}
	
	void GetGlassFromBin() {
		state = RobotState.Working;
		
		// TODO: What kind of glass should we get from the bin?
		myTransducer.fireEvent(TChannel.Robot, TEvent.MOVE_GLASS, null);
		cutter.msgHereIsGlass(new Glass());
	}
	
	// Other
	
	public void setNCCutter(NCCutterAgent nc) {
		cutter = nc;
	}
	
	// Unit test stufff
	
	/* (non-Javadoc)
	 * @see glassline.Robot#printData()
	 */
	@Override
	public void printData() {
		System.out.println("Robot state: " + state);
		System.out.println("Pieces in queue for transport to first conveyor: " + numPiecesInQueue);
	}
}
